package com.cantor.cantorspringbootstarter;

import com.cantor.cantorspringbootstarter.processor.ProviderAppRunner;
import com.cantor.cantorspringbootstarter.processor.ReferenceInjectionProcessor;
import com.cantor.cantorspringbootstarter.processor.ServiceRegisterProcessor;
import com.cantor.consumer.discovery.ServiceDiscoverer;
import com.cantor.core.center.RegistrationCenter;
import com.cantor.core.center.impl.ZooKeeperRegistrationCenter;
import com.cantor.core.config.CantorAppConfig;
import com.cantor.core.config.CantorAppConfigProperties;
import com.cantor.provider.regsitry.ServiceRegistrant;
import com.cantor.provider.start.ProviderBootstrap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

import java.nio.charset.Charset;

@ConditionalOnClass({CantorAppConfig.class, CantorAppConfigProperties.class})
@EnableConfigurationProperties(value = {CantorAutoConfigurationProperties.class})
@Import({ServiceRegisterProcessor.class, ReferenceInjectionProcessor.class, ProviderAppRunner.class})
@Slf4j
public class CantorAutoConfiguration {

    @Autowired
    CantorAutoConfigurationProperties properties;

    // 1. 注册cantor所需的properties类
    @ConditionalOnMissingBean
    @Bean
    CantorAppConfigProperties cantorAppConfigProperties() {
        log.debug("开始注册CantorAppConfigProperties");
        return new CantorAppConfigProperties()
                .setAppName(properties.getAppName())
                .setHost(properties.getHost())
                .setPort(properties.getPort())
                .setProviderConfig(new CantorAppConfigProperties.ProviderConfig()
                        .setVersion(properties.getProvider().getVersion())
                        .setTimeout(properties.getProvider().getTimeout())
                        .setWeight(properties.getProvider().getWeight())
                        .setMock(properties.getProvider().getMock())
                )
                .setConsumerConfig(new CantorAppConfigProperties.ConsumerConfig()
                        .setVersion(properties.getConsumer().getVersion())
                        .setLoadBalance(properties.getConsumer().getLoadBalance())
                        .setTimeout(properties.getConsumer().getTimeout())
                        .setRetries(properties.getConsumer().getRetries())
                        .setMock(properties.getConsumer().getMock())
                );
    }

    // 2. 注册cantor所需的AppConfig类
    @ConditionalOnMissingBean
    @DependsOn("cantorAppConfigProperties")
    @Bean
    CantorAppConfig cantorAppConfig(CantorAppConfigProperties cantorInnerProperties) {
        log.debug("开始注册CantorAppConfig");
        return new CantorAppConfig(cantorInnerProperties);
    }

    // 3. 注册Zookeeper注册中心
    @ConditionalOnMissingBean
    @DependsOn("cantorAppConfig")
    @Bean
    RegistrationCenter registrationCenter() {
        log.debug("开始注册RegistrationCenter");
        return new ZooKeeperRegistrationCenter()
                .setAddress(properties.getCenter().getAddress())
                .setNamespace(properties.getCenter().getNamespace())
                .setEncoding(Charset.forName(properties.getCenter().getEncoding()))
                .setSequenceIdZNode(properties.getCenter().getSequenceIdZNode());
    }

    //////////////////////////////////////////////// Provider //////////////////////////////////////////////////////

    // 1. 注册服务注册器
    @ConditionalOnMissingBean
    @Bean
    ServiceRegistrant serviceRegistrant() {
        log.debug("开始注册ServiceRegistrant");
        ServiceRegistrant registrant = ServiceRegistrant.DEFAULT_REGISTRANT;
        // 扫描包下@CantorService注解的类, 然后注册到registrant里面
        // ...
        return registrant;
    }

    // 2. Provider端启动器
    @Primary
    @DependsOn({"cantorAppConfig", "registrationCenter", "serviceRegistrant"})
    @Bean
    ProviderBootstrap providerBootstrap(CantorAppConfig appConfig, RegistrationCenter center, ServiceRegistrant registrant) {
        log.debug("开始注册ProviderBootstrap");
        return ProviderBootstrap.builder()
                .appConfig(appConfig)
                .center(center)
                .serviceRegistrant(registrant)
                .build();
    }

    //////////////////////////////////////////////// Consumer //////////////////////////////////////////////////////

    @ConditionalOnMissingBean
    @Bean
    ServiceDiscoverer serviceDiscoverer() {
        log.debug("开始注册ServiceDiscoverer");
        return ServiceDiscoverer.DEFAULT_DISCOVERER;
    }

}
